/*
 * mana (library)
 * Copyright (c) 2003 Shun Moriya <shun@mnu.sakura.ne.jp>
 *
 * The MIT License
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*!
 * @file
 * @brief	manaクラスに関するヘッダーファイル
 *
 * このファイルはmanaクラスに関係するヘッダーファイルです。
 * manaクラスは更新やリクエストなどの制御、mana_actor オブジェクトの検索などの
 * 実行環境を表しています。
 *
 * @author	Shun Moriya <shun@mnu.sakura.ne.jp>
 */

#if !defined(___MANA_H___)
#define ___MANA_H___

#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

#if !defined(___MANA_DEFINE_H___)
#include "mana_define.h"
#endif
#if !defined(___MANA_ACTOR_H___)
#include "mana_actor.h"
#endif
#if !defined(___MANA_ARRAY_H___)
#include "mana_array.h"
#endif
#if !defined(___MANA_DATALINK_H___)
#include "mana_datalink.h"
#endif
#if !defined(___MANA_HASH_H___)
#include "mana_hash.h"
#endif
#if !defined(___MANA_INFO_H___)
#include "mana_info.h"
#endif
#if !defined(___MANA_STREAM_H___)
#include "mana_stream.h"
#endif
#include <stddef.h>

/*!
 * @brief	manaクラス
 * manaクラスは実行環境を表しています。
 * C++でいうところのメンバー変数ですが、C言語なので全てpublicになっています。
 * 操作用の関数を用意しているので、それらの関数を利用して操作してください。
 */
typedef struct mana
{
#if 0
	struct mana_actor* map_actor;		/*!< @brief マップを表すmana_actor オブジェクト */
	struct mana_actor* player_actor;	/*!< @brief プレイヤーを表すmana_actor オブジェクト */
#endif
	mana_array actor_array;				/*!< @brief mana_actor オブジェクトへの配列 */
	mana_hash actor_hash;				/*!< @brief mana_actor オブジェクトへの連想配列 */
	mana_hash phantom_hash;				/*!< @brief phantomを表すmana_actor オブジェクトへの連想配列 */
	mana_datalink datalink;				/*!< @brief mana_datalink オブジェクト */
	unsigned char* global_memory;		/*!< @brief グローバル変数格納エリア */
	mana_file_header* file_header;		/*!< @brief ロードされたファイルへのポインタ */
	unsigned char* instruction_pool;	/*!< @brief ロードされたプログラムへのポインタ */
	char* constant_pool;				/*!< @brief ロードされたデータへのポインタ */
	unsigned int frame_counter;			/*!< @brief フレームカウンタ */

/*
	CManaIntersectionManager m_IntersectionManager;
	CManaResource m_Resource;
*/

	unsigned char flag;					/*!< @brief フラグ */
	/*
	 * mana :: flags
	 *
	 *| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
	 *	|	|	|	|	|	|	|	|
	 *	|	|	|	|	|	|	|	+-- MANA_FLAG_AUTO_RELEASE
	 *	|	|	|	|	|	|	+------ MANA_FLAG_DEBUG_MODE
	 *	|	|	|	|	|	+---------- MANA_FLAG_FRAME_CHANGED
	 *	|	|	|	|	+-------------- MANA_FLAG_INIT_ACTION_RUNNING
	 *	|	|	|	+------------------ MANA_FLAG_INIT_ACTION_FINISHED
	 *	|	|	+---------------------- MANA_FLAG_INITIALIZED
	 *	|	+-------------------------- MANA_FLAG_REQUESTED
	 *	+------------------------------ MANA_FLAG_SYSTEM_REQUEST
	 */
}mana;

#define MANA_FLAG_AUTO_RELEASE			(0x01)	/*!< @brief プログラムの自動開放フラグ */
#define MANA_FLAG_DEBUG_MODE			(0x02)	/*!< @brief デバックモードフラグ */
#define MANA_FLAG_FRAME_CHANGED			(0x04)	/*!< @brief フレーム変更フラグ */
#define MANA_FLAG_INIT_ACTION_RUNNING	(0x08)	/*!< @brief initアクション実行中フラグ */
#define MANA_FLAG_INIT_ACTION_FINISHED	(0x10)	/*!< @brief initアクション終了フラグ */
#define MANA_FLAG_INITIALIZED			(0x20)	/*!< @brief 初期化済みフラグ */
#define MANA_FLAG_REQUESTED				(0x40)	/*!< @brief リクエスト発生済みフラグ */
#define MANA_FLAG_SYSTEM_REQUEST		(0x80)	/*!< @brief システムリクエスト許可フラグ */

/*! @brief mana オブジェクトの生成 */
extern mana* mana_create(void);

/*! @brief mana オブジェクトの破棄 */
extern void mana_destroy(mana* self);

/*! @brief mana オブジェクトのシリアライズ */
extern void mana_serialize(mana* self, mana_stream* stream);

/*! @brief mana オブジェクトのデシリアライズ */
extern void mana_deserialize(mana* self, mana_stream* stream);

/*! @brief manaプログラムの読み込み */
extern mana_bool mana_load_program(mana* self, void* program, int auto_release);

/*! @brief manaプログラムの開放 */
extern void mana_unload_program(mana* self);

/*! @brief manaプログラムアドレスの取得 */
extern void* mana_get_program_buffer(mana* self);

/*! @brief 再起動 */
extern void mana_restart(mana* self);

/*! @brief 同期更新 */
extern mana_bool mana_run(mana* self, float second);

/*! @brief 非同期更新 */
extern void mana_execute(mana* self);

/*! @brief 実行中か調べる */
extern mana_bool mana_is_running(mana* self);

/*! @brief 全アクターにリクエストを要求 */
extern void mana_request_all(mana* self, int level, const char* action_name, mana_actor* sender);

/*! @brief アクターにリクエストを要求 */
extern mana_bool mana_request(mana* self, int level, const char* actor_name, const char* action_name, mana_actor* sender);

/*! @brief 処理を譲る */
extern void mana_yield(mana* self);

extern char mana_get_char(const mana* self, const unsigned char* address);
extern short mana_get_short(const mana* self, const unsigned char* address);
extern int mana_get_integer(const mana* self, const unsigned char* address);
extern unsigned char mana_get_unsigned_char(const mana* self, const unsigned char* address);
extern unsigned short mana_get_unsigned_short(const mana* self, const unsigned char* address);
extern unsigned int mana_get_unsigned_integer(const mana* self, const unsigned char* address);
extern float mana_get_float(const mana* self, const unsigned char* address);
extern const char* mana_get_string(const mana* self, const unsigned char* address);
extern unsigned char* mana_get_address(const mana* self, const unsigned char* address);

/*! @brief アクターオブジェクトを取得 */
extern struct mana_actor* mana_get_actor(mana* self, const char* name);

/*! @brief アクターの名前を取得 */
extern const char* mana_get_actor_name(mana* self, struct mana_actor* actor);

/*! @brief アクターのコピー */
extern struct mana_actor* mana_create_actor(mana* self, struct mana_actor* actor, const char* new_name);

/*! @brief アクターのコピー */
extern struct mana_actor* mana_create_actor_name(mana* self, const char* name, const char* new_name);

/*! @brief phantomを元にアクターを生成 */
extern struct mana_actor* mana_create_actor_from_phantom(mana* self, const char* name, const char* new_name);

/*! @brief initアクション実行中か取得 */
extern mana_bool mana_is_in_init_action(mana* self);

/*! @brief initアクション終了か取得 */
extern mana_bool mana_is_finish_init_action(mana* self);

/*! @brief システムリクエストの許可フラグを設定 */
extern void mana_enable_system_request(mana* self, const mana_bool enable);

/*! @brief システムリクエストの許可フラグを取得 */
extern mana_bool mana_is_system_request_enabled(mana* self);

/*! @brief フレームカウンターを取得 */
extern unsigned int mana_get_frame_counter(mana* self);

/*! @brief フレームが変更されたか取得 */
extern mana_bool mana_is_frame_changed(mana* self);

/*! @brief リソースデータを取得 */
extern void mana_get_data(const mana* self, const int resouce_id, const void** buffer, size_t* size);

#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) || defined(c_plusplus)
}
#endif

#endif
